#pragma once

#include "fwddecl.h"
#include "impl\buffer_impl.h"

namespace blu
{
	typedef impl::BufferUsage buffer_usage;

	template <buffer_usage Usage>
	class buffer
	{
		typedef impl::Buffer<Usage> MyImpl;
	private:
		MyImpl _impl;
	public:
		typedef typename MyImpl::size_type size_type;

		buffer(device &dvc)
			:_impl(impl::implAccess::getImpl(dvc))
		{

		}

		buffer(device &dvc, size_type size)
			:_impl(impl::implAccess::getImpl(dvc), size)
		{

		}

		template <typename ElemTy>
		buffer(device &dvc, const ElemTy *carr, size_type size)
			:_impl(impl::implAccess::getImpl(dvc), reinterpret_cast<const char*>(carr),
				size * sizeof(ElemTy))
		{

		}

		template <typename ContiguousContainer>
		buffer(device &dvc, const ContiguousContainer &arr)
			:buffer(dvc, arr.data(), static_cast<size_type>(arr.size()))
		{
		}

		template <typename ElemTy>
		void write(const ElemTy *carr, size_type size, size_type offset = 0)
		{
			_impl.write(reinterpret_cast<const char*>(carr),
				static_cast<size_type>(size * sizeof(ElemTy)),
				offset);
		}

		template <typename ContiguousContainer>
		void write(const ContiguousContainer &arr, size_type offset = 0)
		{
			write(arr.data(), static_cast<size_type>(arr.size()), offset);
		}

		size_type size() const
		{
			return _impl.size();
		}
	};

	typedef buffer<buffer_usage::generic> generic_buffer;

	typedef buffer<buffer_usage::vertex_indices> index_buffer;

	typedef buffer<buffer_usage::indirect_arguments> indirect_args_buffer;

	typedef buffer<buffer_usage::program_static_memory> program_static_buffer;

	template <typename Buffer, typename Ty>
	class buffered_array_view
	{
	public:
		std::uint32_t offset() const
		{

		}

		std::uint32_t stride() const
		{

		}

		std::uint32_t element_size() const
		{

		}
	};

}